#include "CowString.hpp"
#include <string.h>

using std::cout;
using std::endl;

char * CowString::malloc(const char * pstr){
    if(pstr == nullptr){
        //无参构造
        return new char[1 + kRefCountLength]() + kRefCountLength;
    }
    else{
        //C风格字符串构造
        return new char[strlen(pstr) + kRefCountLength + 1]() + kRefCountLength;
    }
}

//无参构造
CowString::CowString()
:_pstr(malloc())
{
    initRefConut();
    cout << "CowString()" << endl;
}

//C风格字符串构造
CowString::CowString(const char * pstr)
:_pstr(malloc(pstr))
{
    strcpy(_pstr, pstr);
    initRefConut();
    cout << "CowString(const char *)" << endl;
}

//拷贝构造
CowString::CowString(const CowString & rhs)
:_pstr(rhs._pstr)//浅拷贝
{
    increasekRefCount();
    cout << "CowString(const CowString &)" << endl;
}

CowString & CowString::operator=(const CowString & rhs)
{
    //1. 考虑是否自复制
    if(this != &rhs){
        //2. 是否要回收之前的空间
        decreasekRefCount();
        if(useCount() == 0){
            delete [] (_pstr - kRefCountLength);
            _pstr = nullptr;
        }
        //3. 进行浅拷贝
        _pstr = rhs._pstr;
        increasekRefCount();
        cout << "Cowtring::operator=" << endl;
    }
    return *this;
}

//下标访问运算符
CowString::charPoxy CowString::operator[](ssize_t idx){
    cout << "Cowtring::operator[]" << endl;
    return charPoxy(*this, idx);
}

CowString::~CowString(){
    decreasekRefCount();
    if(useCount() == 0){
        delete [] (_pstr - kRefCountLength);
        _pstr = nullptr;
        cout << "heap delete" << endl;
    }
}

const char * CowString::c_str() const{
    return _pstr;
}

size_t CowString::size() const{
    return strlen(_pstr);
}

void CowString::initRefConut(){
    *(int *)(_pstr-kRefCountLength) = 1;
}
void CowString::increasekRefCount(){
    ++*(int *)(_pstr-kRefCountLength);
}
void CowString::decreasekRefCount(){
    --*(int *)(_pstr-kRefCountLength);
}
size_t CowString::useCount(){
    return *(int *)(_pstr-kRefCountLength);
}

ostream & operator<<(ostream & os, const CowString & rhs){
    os << rhs._pstr;
    return os;
}
//end of class CowString


//class charPoxy
CowString::charPoxy::charPoxy(CowString & rhs, ssize_t idx)
:_self(rhs)
{
    _idx = idx;
    cout << "CowString::charPoxy::charPoxy(CowString &)" << endl;
}
CowString::charPoxy::~charPoxy(){}

ostream & operator<<(ostream & os, const CowString::charPoxy & rhs){
    cout << "CowString::charPoxy::operator<<()" << endl;
    os << rhs._self._pstr[rhs._idx];
    return os;
}
char & CowString::charPoxy::operator=(const char ch){
    cout << "CowString::charPoxy::operator=()" << endl;
    //1. 考虑是否越界
    if(_idx < _self.size()){
        //2. 传入的字符串和原来的是否相等
        if(_self._pstr[_idx] == ch){
            //自复制
            return _self._pstr[_idx];
        }
        else{
            //3. 原来的空间是否回收
            _self.decreasekRefCount();
            if(_self.useCount() == 0){
                char * ptmp = _self.malloc(_self._pstr);//4. 深拷贝
                strcpy(ptmp, _self._pstr);
                delete [] (_self._pstr - _self.kRefCountLength);
                _self._pstr = ptmp;
                _self.initRefConut();
                _self._pstr[_idx] = ch;//5. 修改字符
            }
            else{
                char * ptmp = _self.malloc(_self._pstr);//4. 深拷贝
                strcpy(ptmp, _self._pstr);
                _self._pstr = ptmp;
                _self.initRefConut();
                _self._pstr[_idx] = ch;//5. 修改字符
            }
            return _self._pstr[_idx];
        }
    }
    else{
        cout << "out of range" << endl;
        static char nullchar = '\0';
        return nullchar;
    }
}